/* Author: Jovica Aleksic

*/
/*global window, jQuery, al*/
var mr;
(function($) {
	mr = {
		utils: {
			ucfirst: function(string)	{
			    return string.charAt(0).toUpperCase() + string.slice(1);
			}
		},
		hash: {
			/**
			 * Gibt den aktuellen Hash, also den Teil der IURL nach einer Raute ('#'), zurück
			 * @return der aktuelle Hash
			 */
			get: function() {
				var hash = window.location.hash;
				if (hash) {
					if (hash.match(/\/\//)) {
						mm.sethash(hash.replace('#/','').replace(/\/\//g,'/'));
					}
					return hash.replace('/','').replace('#','');
				}
			},
			
			/**
			 * Setzt den hash in der Adresszeile, also den Teil nach der Raute ('#'), um damit einen Seitenwechsel zu initiieren.
			 * @param value Der neue Wert für den Hash
			 */
			set: function(/**String*/ value) {
				if (value && value.charAt(0) === '/') {
					value = value.substr(1, value.length);
				}
				value = value.replace(/\/\//g, '/');
				window.location.href = '#/'+value;
			}
		},
		defaults: {
			mediaelement: {
			    enablePluginDebug: false,
			    plugins: ['flash'],
			    pluginPath: './js/libs/mediaelement/',
			    mode: 'shim',
			    timerRate: 250
			}
		}
	}
	
	mr.Site = {
		namespace: 'mr',
		classname: 'Site',
		
		element: null,
		bgVideo: null,
		pages: null,
		currentPage: null,
		oldPage: null,
		inTransition: false,
		
		init: function() {
			this._super();
			
			this.element = $('.site').show();
			this.bgVideo = new mr.BGVideo(this);
			this.createPages();
			
			$(window).bind(this.ns('hashchange'), $.proxy(this.handleHashChange, this));
			$(window).bind(this.ns('beforeunload'), $.proxy(this.handleBeforeUnload, this));
			this.showPage(mr.hash.get() || 'intro', true);
			this.trigger('ready');
		},
		handleBeforeUnload: function() {
			if (this.currentPage) {
				this.currentPage.destroy();
			}
		},
		createPages: function() {
			var self = this;
			self.pages = [];
			this.element.find('.page').each(function() {
				var PageClass = mr.utils.ucfirst( $(this).attr('class').split('page-')[1].split(' ')[0] ) + 'Page';
				if (!mr[PageClass]) {
					self.error('Class not found: mr.'+PageClass);
				}
				else {
					self.pages.push(new mr[PageClass](self, this));
				}
			});
		},
		getPage: function(pagehash) {
			var result;
			$(this.pages).each(function() {
				if (this.hash === pagehash) {
					result = this;
				}
			});
			return result;
		},
		showPage: function(pagehash, instant) {
			//this.log('showPage', pagehash);
			this.trigger('showPage', [pagehash]);
			var self = this,
				pageOld = this.currentPage,
				pageNew = this.getPage(pagehash),
				
				showNew = function() {
					self.currentPage = pageNew;
					self.currentPage.bind(self.ns('showDone'), function() {
						self.currentPage.unbind(self.ns('showDone'));
						self.inTransition = false;
						self.trigger('showPageDone', [pagehash]);
					});
					self.currentPage.show(instant);
					if (window._gaq) {
						window._gaq.push(['_trackPageview', '/' + this.hash]);
					}
				},
				
				hideOld = function() {
					self.oldPage = pageOld; 
					self.oldPage.bind(self.ns('hideDone'), function() {
						self.oldPage.unbind(self.ns('hideDone'));
						showNew();
					});
					self.oldPage.hide(instant);
				}
			;
			if (!pageNew) {
				this.error('showPage()', 'Page unavailable: ', pagehash);
				return;
			}
			
			this.inTransition = true;
			if (!pageNew.element.is('.type-overlay') && pageOld) {
				hideOld();
			}
			else {
				showNew();
			}
		},
		handleHashChange: function() {
			var hash = mr.hash.get();
			this.showPage(hash);
		}
	};
	mr.Site = al.Class.extend(mr.Site);
	
	
	
	/*
	 * ========================================================
	 * PAGES
	 * ========================================================
	 */
	
	/**
	 * Page
	 * Base class for an element-based page class
	 */
	mr.Page = {
		namespace: 'mr',
		classname: 'Page',
		hash: null,
		title: null,
		
		defaults: function() {
			return this.merge(this._super(), {
				tweenDuration: 150
			});
		},
		
		init: function(site, el) {
			this._super();
			this.site = site;
			this.element = $(el);
			this.title = this.element.attr('title');
			this.element.attr('title', '');
			this.container = this.element.parent();
			this.hide(true);
		},
		
		hide: function(instant) {
			var o = this.options,
				d = instant===true ? 0 : o.tweenDuration,
				self = this;
			this.trigger('hide');
			this.element.stop().animate({opacity: 0}, d, function() {
				self.hideDone();
				self.trigger('hideDone');
				self.element.remove();
			});
			$(window).unbind(this.ns('resize'));
		},
		hideDone: function() {
			
		},
		show: function(instant) {
			var o = this.options,
			d = instant===true ? 0 : o.tweenDuration,
				self = this;
			this.element.css({opacity: 0});
			this.element.appendTo(this.container);
			this.element.stop().animate({opacity:1}, d, function() {
				self.showDone();
				if (self.title) {
					window.document.title = self.title;
				}
				self.trigger('showDone');
			});
			this.trigger('show');
			$(window).bind(this.ns('resize'), $.proxy(this.handleResize, this));
			this.resize()
		},
		showDone: function() {
			
		},
		
		handleResize: function() {
			this.resize();
		},
		resize: function() {
			if (this.site.bgVideo.currentSize) {
				this.element.css({
					width: this.site.bgVideo.currentSize.width
				});
			}
			else {
				
			}
		}
		
	};
	mr.Page = al.Class.extend(mr.Page);
	
	
	/**
	 * IntroPage
	 */
	mr.IntroPage = {
		namespace: 'mr',
		classname: 'IntroPage',
		hash: 'intro',
		init: function(site, el) {
			this._super(site, el);
		}	
	};
	mr.IntroPage = mr.Page.extend(mr.IntroPage);

	/**
	 * MainPage
	 */
	mr.MainPage = {
		namespace: 'mr',
		classname: 'MainPage',
		hash: 'main',
		init: function(site, el) {
			this._super(site, el);
		},
		show: function() {
			this._super();
			this.site.bgVideo.play();
		}
	};
	mr.MainPage = mr.Page.extend(mr.MainPage);

	mr.GridPage = {
		namespace: 'mr',
		classname: 'GridPage',
		hash: 'grid',
		init: function(site, el) {
			this._super(site, el);
			this.site.bgVideo.hide();
			this.site.bgVideo.pause();
		},
		show: function() {
			this._super();
			this.site.bgVideo.pause();
			this.createGrid();
		},
		
		hide: function() {
			this._super();
			this.site.bgVideo.play();
		},
		
		
		createGrid: function() {
			
			var getPageFiles = function() {
				var files = [];
				$('input[name=video]').each(function() {
					var file = $(this).val();
					files.push(file.match(/http\:/) ? file : '../' + file);
				});
				return JSON.stringify(files);
			};
			
			var scale = 0.85;
			
			var config = {
				elementID: 'flashgrid',
				swfPath: 'swf/VideoGrid.swf',
				swfWidth: null /* defined later */,
				swfHeight: null /* defined later */,
				fpVersion: '10.0',
				xiPath: 'swf/expressInstall.swf',
				embedCallback: null,
				
				/**
				 * ======================================================
				 * grid setup
				 * ======================================================
				 */
				flashvars: {
					
					/**
					 * Whether to use developer features. Disable it on your live site. 
					 */
					debug: false,
					
					/**
					 * The video files to be included in the grid.
					 * Note: paths are relative to the main swf, probably you must add the prefix '../'.
					 */
					files: getPageFiles(),
					
					/**
					 * Amount of columns in the grid. Rows will be generated automatically until all videos fit inside the grid.
					 */
					gridColumns: 3,
					
					gridAutoCenter: false,
					
					gridOffsetX: 0,
					
					gridOffsetY: 0,
					
					/**
					 * Width of each video in the grid.
					 */
					itemWidth: 220 * scale,
					
					/**
					 * Height of each video in the grid.
					 */
					itemHeight: 165 * scale,
					
					/**
					 * Distance between each video in the grid.
					 */
					itemDistance: 5,
					
					/**
					 * Whether playback of individual videos can be toggled by clicking on them.
					 */
					itemToggleOnClick: true,
					
					/**
					 *	Controls how the video will be scaled to fit the area. The following values are recognized:
					 *		"stretch" (the default) - The video will fill the width/height exactly.
					 *		"proportionalInside" - The video will be scaled proportionally to fit inside the area defined by the width/height
					 *		"proportionalOutside" - The video will be scaled proportionally to completely fill the area, allowing portions of it to exceed the bounds defined by the width/height.
					 *		"widthOnly" - Only the width of the video will be adjusted to fit.
					 *		"heightOnly" - Only the height of the video will be adjusted to fit.
					 *		"none" - No scaling of the video will occur.
					 * 
					 * (http://www.greensock.com/as/docs/tween/com/greensock/loading/VideoLoader.html)
					 */
					videoScaleMode: 'stretch',
					
					/**
					 * Amount of seconds to be buffered before a video starts playing
					 */
					videoBufferTime: 5,
					
					/**
					 * Whether videos automatically start playback as soon as enough has been buffered.
					 */
					videoAutoPlay: true,
					
					itemScale: 1.1,
					itemOffsetY: -5,
					
					syncStart: true,
					
					bgColor: '0x000000',
					
					bgAlpha: 0.5
				},
				
				flashparams: {
					bgcolor: '#000000',
					allowscriptaccess: 'always',
					wmode: 'transparent'
				},
				
				flashattribs: {
					
				}
	
				
				
			};
	
			config.swfWidth = config.flashvars.gridColumns * config.flashvars.itemWidth + (config.flashvars.gridColumns-1) * config.flashvars.itemDistance,
			config.swfHeight = config.flashvars.gridColumns * config.flashvars.itemHeight + (config.flashvars.gridColumns-1) * config.flashvars.itemDistance,
			
			Videogrid('create', config);
		
		},
		
		destroyGrid: function() {
			Videogrid('destroy', this.gridID)
		},
		
		
		
		
		
		destroy: function() {
			this.destroyGrid();
			this._super();
		}
	};
	mr.GridPage = mr.Page.extend(mr.GridPage);
	 
	/**
	 * StillsPage
	 */
	mr.StillsPage = {
		namespace: 'mr',
		classname: 'StillsPage',
		hash: 'stills',
		title: 'Monument Remove - Stills',
		
		init: function(site, el) {
			this._super(site, el);
		},
		
		show: function() {
			this._super();
			this.site.bgVideo.hide();
			this.site.bgVideo.pause();
			this.element.find('a.fancy').fancybox({
				overlayColor: '#000',
				overlayOpacity: 0.85,
				centerOnScroll: true
			});
			$(window).bind(this.ns('resize'), $.proxy(this.handleResize, this));
			this.element.find('.contents').show();
			this.resize();
		},
		hide: function() {
			this._super();
			this.site.bgVideo.show();
			this.site.bgVideo.play();
			$(window).unbind(this.ns('resize'));
		},
		
		handleResize: function() {
			this.resize();
		},
		
		resize: function() {
			var winWidth = $(window).width(),
				imgWidth = this.element.find('.still').first().outerWidth(),
				possibleColumns = Math.floor(winWidth / imgWidth),
				gridWidth =  possibleColumns * imgWidth;
			
			this.element.find('.stills').css({
				position: 'relative',
				width: gridWidth,
				left: 0.5 * (winWidth - gridWidth)
			});
			this.element.find('.btn-back').css({
				left:this.element.find('.stills').css('left')
			})
		}
		
	};
	mr.StillsPage = mr.Page.extend(mr.StillsPage);
	

	mr.BGVideo = {
		namespace: 'mr',
		classname: 'BGVideo',
		ready: false,
		paused: false,
		defaults: function() {
			return this.merge(this._super(), {
				widthFactor: 1,
				heightFactor: 1,
				origWidth: 600,
				origHeight: 480
			});
		},
		init: function(site) {
			this._super();
			this.site = site;
			this.site.bind('ready', $.proxy(this.load, this));
			this.element = $('.bg-video');
			$(window).bind('resize', $.proxy(this.handleResize, this));
			this.resize();
			$(window).bind('click', $.proxy(this.handleClick, this));
		},
		load: function() {
			var vid = this.element.find('video');
			vid.attr('src', vid.attr('data-src'));
			this.mediaElement = new MediaElement(vid.attr('id'), this.merge(mr.defaults.mediaelement, {
			    success: $.proxy(this.handleMeSuccess, this),
			    error: $.proxy(this.handleMeError, this)
			}));
		},
		handleMeSuccess: function () {
			this.ready = true;
			this.mediaElement.play();
			this.resize();
			this.trigger('ready');
	    },
	    handleMeError: function () { 
	    	this.error.apply(this, arguments);
	    },
	    handleResize: function() {
	    	this.resize();
	    },
		resize: function() {
			var o = this.options,
				el = this.element,
				w = $(window).width() * o.widthFactor,
				h = $(window).height() * o.heightFactor,
				swf = (el.find('embed').length ? el.find('embed') : el.find('object'))
				.attr({
					width: w,
					height: h
				})
				.css({
					width:w,
					height: h
				})
			;
			if (swf && swf.length) {
				swf[0].setVideoSize(w, h);
			}
			this.currentSize = {
				height: h,
				width: h * (this.options.origWidth / this.options.origHeight)
			}
		},
		
		play: function() {
			if (this.ready) {
				this.paused = false;
				this.mediaElement.play();
			}
			else {
				this.bind(this.ns('ready') + '_play', $.proxy(function() {
					this.unbind(this.ns('ready') + '_play');
					this.paused = false;
					this.mediaElement.play();
				}, this));
			}
		},
		pause: function() {
			if (this.ready) {
				this.paused = true;
				this.mediaElement.pause();
			}
			else {
				this.bind(this.ns('ready') + '_pause', $.proxy(function() {
					this.paused = true;
					this.unbind(this.ns('ready') + '_play');
					this.mediaElement.pause();
				}, this));
			}
		},
		togglePlayback: function() {
			if (this.paused) {
				this.play();
			}
			else {
				this.pause();
			}
		},
		handleClick: function(e) {
			if($(e.target).is('.page')) {
				this.togglePlayback();
			}
		},
		show: function() {
			this.element.css('visibility', 'visible');
		},
		hide: function() {
			this.element.css('visibility', 'hidden');
		}
	};
	mr.BGVideo = al.Class.extend(mr.BGVideo);
	
	
	$(function() {
		window.site = new mr.Site();
	});
}(jQuery));
 